<!DOCTYPE html>
<html lang="en">
<head>
    <title>囧么肥事</title>
    <meta charset="UTF-8"/>
    <meta name="viewport"
          content="width=device-width,height=device-height,initial-scale=1.0,maximum-scale=1.0,user-scalable=0"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta http-equiv="Content-Type" content="text/html;"/>
    <meta name="renderer" content="webkit">
    <!--解决页面加载网络图片的403问题 , 可以让img标签预加载网络图片-->
    <meta name="referrer" content="no-referrer" />

    <!--markdown S -->
    <link rel="stylesheet" type="text/css" href="../../static/css/export_setting_css.css"/>
    <link rel="stylesheet" type="text/css" href="../../static/css/markdown_preview_css.css"/>
    <!--markdown E -->

    <!--left bar tools css E-->
    <link rel="stylesheet" type="text/css" href="../../static/css/nav.css">
    <link rel="stylesheet" type="text/css" href="http://www.jq22.com/jquery/font-awesome.4.6.0.css">
    <!--left bar tools css E-->

    <!-- 滚动条 S -->
    <link rel="stylesheet" href="../../static/css/optiscroll.css">
    <!-- 滚动条 E -->
</head>
<body>
<div id="m-wrapper" class="m-wrapper optiscroll">
    <!-- top 锚点 -->
    <a id="top"></a>

    <!-- left bar tools S -->
    <div class="leftNav-item">
        <ul>
            <li>
                <i class="fa fa-location-arrow"></i>
                <a href="http://jiongmefeishi.gitee.io/monster-blog/" target="_blank" class="rota">个人网站</a>
            </li>

            <li title="Git">
                <i class="fa fa-code-fork" aria-hidden="true"></i>
                <a href="http://jiongmefeishi.gitee.io/monster-blog/" target="_blank" class="rota">Git Page</a>
            </li>

            <li lay-data="img" data-fooc="http://resource.zqtaotao.cn/wx/qrcode/jiongmefeishi.jpg">
                <i class="fa fa-comments-o"></i><a href="javascript:;" class="rota">公众号</a>
            </li>

            <li lay-data="img" data-fooc="http://resource.zqtaotao.cn/weixincode.png">
                <i class="fa fa-money"></i><a href="javascript:;" class="rota">小额打赏</a>
            </li>
            <li title="返回顶部" class="for-top">
                <i class="fa fa-arrow-up"></i>
                <a href="#top" class="rota">去顶部</a>
            </li>
        </ul>
    </div>
    <!-- left bar tools E -->

    <!--content S-->
    <div id="export_content"><div class="output_wrapper" id="output_wrapper_id"><figure><img src="https://img-blog.csdnimg.cn/img_convert/f624544138ac5e8f9d6851002393486d.png" alt="标题" title="标题"><figcaption>标题</figcaption></figure>
        <h1 id="hmysql"><span>《MySQL面试小抄》查询缓存</span></h1>
        <p>我是肥哥，一名不专业的面试官！</p>
        <p>我是囧囧，一名积极找工作的小菜鸟！</p>
        <blockquote>
            <p><strong>囧囧表示：小白面试最怕的就是面试官问的知识点太笼统，自己无法快速定位到关键问题点！！！</strong></p>
        </blockquote>
        <hr>
        <p>本期主要面试考点</p>
        <pre><code class="hljs">面试官考点之简述一下什么是查询缓存机制？<br></code></pre>
        <pre><code class="hljs">面试官考点之查询如何命中缓存？<br></code></pre>
        <pre><code class="hljs">面试官考点之什么场景下SQL和结果集不会被缓存？<br></code></pre>
        <pre><code class="hljs">面试官考点之什么场景下会导致MySQL缓存失效？<br></code></pre>
        <pre><code class="hljs">面试官考点之查询缓存是如何进行内存管理的？<br></code></pre>
        <pre><code class="hljs">面试官考点之MySQL是一次性分配所有的内存空间吗？<br></code></pre>
        <pre><code class="hljs">面试官考点之缓存中的内存碎片无法避免，那么有什么办法优化吗？<br></code></pre>
        <pre><code class="hljs css">面试官考点之<span class="hljs-selector-tag">MySQL4</span><span class="hljs-selector-class">.0</span>提出了查询缓存，它设计出来是为了加速哪些查询场景？<br></code></pre>
        <pre><code class="hljs css">面试官考点之<span class="hljs-selector-tag">MySQL5</span><span class="hljs-selector-class">.6</span>中默认禁用，8<span class="hljs-selector-class">.0</span>以后完全移除，造成这个改变的原因是什么？<br></code></pre>
        <pre><code class="hljs">面试官考点之生产环境要不要开启MySQL缓存？<br></code></pre>
        <hr>
        <figure><img src="https://img-blog.csdnimg.cn/img_convert/eebbb88837ad52345b80db9156876d66.png" alt="qc1" title="qc1"><figcaption>qc1</figcaption></figure>
        <figure><img src="https://img-blog.csdnimg.cn/img_convert/f50a2570770965316fa8165f47f3f054.png" alt="qc2" title="qc2"><figcaption>qc2</figcaption></figure>
        <h3 id="h"><span>面试官考点之简述一下什么是查询缓存机制？</span></h3>
        <p>MySQL服务器高负载情况下，我们需要采取一种措施给服务器减轻压力，一个复杂的查询是非常消耗性能的，</p>
        <p>其中磁盘IO又占据主要资源，缓存是对系统性能优化的一种重要手段。</p>
        <blockquote>
            <p>查询缓存机制设计是为了从根本上减少磁盘IO次数，MySQL开启缓存后，将SQL和结果集以键值对KV的形式存储在内存中。</p>
            <p>当相同的SQL再次进入，MySQL识别是相同查询喉，会直接返回缓存在内存中的结果集。</p>
            <p>避免再次进行一系列复杂的解析优化和磁盘IO过程。</p>
        </blockquote>
        <h3 id="h-1"><span>面试官考点之查询如何命中缓存？</span></h3>
        <pre><code class="hljs sql"><span class="hljs-keyword">select</span>&nbsp;<span class="hljs-keyword">id</span>&nbsp;<span class="hljs-keyword">from</span>&nbsp;<span class="hljs-keyword">user</span>;<br><br><span class="hljs-keyword">select</span>&nbsp;<span class="hljs-keyword">id</span>&nbsp;<span class="hljs-keyword">FROM</span>&nbsp;<span class="hljs-keyword">user</span>;<br></code></pre>
        <blockquote>
            <p>上面语句能命中缓存吗？</p>
        </blockquote>
        <p>MySQL缓存命中机制有严格苛刻的要求，在判断命中前，MySQL不会对SQL做任何的解析处理。</p>
        <pre><code class="hljs">SQL上的任何字符的不同，如大小写、空格、注释等都会导致缓存不命中<br></code></pre>
        <p>所以上面查询时无法命中缓存的。</p>
        <h3 id="hsql"><span>面试官考点之什么场景下SQL和结果集不会被缓存？</span></h3>
        <p>或者说缓存规则是什么？</p>
        <blockquote>
            <p>第一种情况：查询语句中包含不确定数据</p>
        </blockquote>
        <pre><code class="hljs vbscript">例如查询语句中包含不确定函数：<span class="hljs-built_in">NOW</span>()、CURRENT_DATE()等。<br><br>因为每次执行这类带了不确定数据的查询所返回结果可能是不同的。<br></code></pre>
        <blockquote>
            <p>第二种情况：超过了query_cache_limit预设阈值</p>
        </blockquote>
        <pre><code class="hljs">超出了缓存内存能承受的范围，将放弃缓存！<br></code></pre>
        <h3 id="hmysql-1"><span>面试官考点之什么场景下会导致MySQL缓存失效？</span></h3>
        <p>任何对于<strong>表结构或者表数据的更新操作</strong>，一定会造成查询缓存中的数据失效，同时查询缓存值的相关条目也会被清空。</p>
        <p>MySQL判定有更新操作，就会设置所有的查询缓存失效。</p>
        <h3 id="h-2"><span>面试官考点之查询缓存是如何进行内存管理的？</span></h3>
        <p>MySQL服务启动，缓存机制会在内存中开辟一块内存，</p>
        <p>其中会<code>划分出一块区域</code>专用来管理维护缓存数据的<strong>元数据</strong>。</p>
        <p>例如空间内存、数据表和查询结果的映射，SQL和查询结果的映射</p>
        <p>MySQL缓存机制将剩余的空闲空间分为一个个小<strong>数据块</strong>，用来存储缓存结果。</p>
        <pre><code class="hljs">每个小块中存储自身的类型，大小和查询结果数据，还有指向前后内存块的指针<br></code></pre>
        <h3 id="hmysql-2"><span>面试官考点之MySQL是一次性分配所有的内存空间吗？</span></h3>
        <p>MySQL因为无法预知查询结果大小，所以无法为每个查询结果精确分配大小恰好匹配的缓存空间。</p>
        <p>MySQL缓存机制采用的是边查边存，动态的去申请缓存内存。</p>
        <blockquote>
            <p>一条SQL查询缓存分配内存过程是怎么样的？</p>
        </blockquote>
        <p>当有查询结果需要缓存的时候，MySQL缓存机制会在SQL查询开始（还未得到结果）时就去申请一块内存空间（小数据块），在不断查询中，<code>如果发现不够则继续申请</code>，<code>如果存储完时有空余则释放多余的内存空间</code>。</p>
        <p>如果余下的需要回收的空间很小，小于query_cache_min_res_unit，不能再次被使用，可能会造成内存碎片，影响查询性能。</p>
        <h3 id="h-3"><span>面试官考点之缓存中的内存碎片无法避免，那么有什么办法优化吗？</span></h3>
        <p>没有什么办法能够完全避免内存碎片，但是选择合适的</p>
        <blockquote>
            <p>query_cache_min_res_unit</p>
        </blockquote>
        <p>可以减少由碎片导致的内存空间浪费。</p>
        <pre><code class="hljs">值太小，则浪费的空间更少，但是会导致频繁的内存块申请操作<br></code></pre>
        <pre><code class="hljs">如果设置得太大，那么碎片会很多<br></code></pre>
        <p><code>调整合适的值其实是在平衡内存浪费和CPU消耗</code></p>
        <blockquote>
            <p>那么我如何确定这个平衡值？</p>
        </blockquote>
        <p>可以通过内存实际消耗，计算单个查询的平均缓存大小</p>
        <pre><code class="hljs">（query_cache_size&nbsp;-&nbsp;Qcache_free_memory）/&nbsp;Qcache_queries_in_cahce<br></code></pre>
        <p>通过查看闲置内存块数量（Qcahce_free_blocks）来观察碎片。</p>
        <blockquote>
            <p>如果产生的碎片过多，通过什么方法可以整理碎片？</p>
        </blockquote>
        <pre><code class="hljs">通过FLUSH_QUERY_CAHCE清理碎片<br><br>这个命令将所有的查询缓存重新排序，<br><br>并将所有的空闲空间都聚焦到查询缓存的一块区域上。<br></code></pre>
        <h3 id="hmysql40"><span>面试官考点之MySQL4.0提出了查询缓存，它设计出来是为了加速哪些查询场景？</span></h3>
        <blockquote>
            <p>1、并发性和查询QPS不高<br>2、被访问的底层数据本质上是静态或半静态的<br>3、查询密集型应用，更新频率非常低而只读查询频率非常高的场景</p>
        </blockquote>
        <h3 id="hmysql5680"><span>面试官考点之MySQL5.6中默认禁用，8.0以后完全移除，造成这个改变的原因是什么？</span></h3>
        <p>理想情况下，上述查询场景非常适合使用查询缓存，但是<code>实际的业务系统都是有CRUD操作</code>的。</p>
        <p>在MySQL里QC是由一个全局锁在控制，每次更新QC的内存块都需要进行锁定，数据更新频繁，就会不断的失效缓存操作，同时缓存失效会造成大量的查询<code>缓存碎片化</code>，还会导致服务器的负载升高，影响数据库的稳定性。</p>
        <p>所以MySQL官方经过抉择，果断移除了查询缓存模块。</p>
        <h3 id="hmysql-3"><span>面试官考点之生产环境要不要开启MySQL缓存？</span></h3>
        <p>建议不开启</p>
        <pre><code class="hljs">根据MySQL官方的测试，如果对一个表执行简单的查询，<br><br>设置每次查询都不一样，<br><br>打开QC后，性能反而下降了13%左右<br></code></pre>
        <p>当然实际业务中，不会都是这种不同的请求，因此实际影响应该比这个小一些。</p>
        <pre><code class="hljs">MySQL查询缓存的目的是为了提升查询性能，但它本身也是有性能开销的。<br></code></pre>
        <p>需要在合适的<code>业务场景下（读写压力模型）</code>使用</p>
        <pre><code class="hljs">不合适的业务场景不但不能提升查询性能，查询缓存反而会变成MySQL的瓶颈。<br><br>对写密集型的应用场景来说，禁用缓存反而提高性能。<br></code></pre>
        <hr>
        <p><strong>推荐MySQL相关休闲阅读</strong>：</p>
        <p>第一段，索引面试题推荐阅读一：<a href="https://mp.weixin.qq.com/s?__biz=Mzg3NjU0NDE4NQ==&amp;mid=2247483708&amp;idx=1&amp;sn=2bba08c79535caad22571efa8f698aa6&amp;chksm=cf31e8eaf84661fc013c8fffd5580f5793c157c5639afdf1a3daa2381be4f6a3347690c770b7#rd">【来自面试官一面MySQL索引的连续灵魂拷问】</a></p>
        <p>第二段，索引面试题推荐阅读二：<a href="https://mp.weixin.qq.com/s?__biz=Mzg3NjU0NDE4NQ==&amp;mid=2247483727&amp;idx=1&amp;sn=de099056011f1da943a0f42843e0c75b&amp;chksm=cf31e899f846618f8d8135ace8b3ca3987a255295b603c463eecd5321806a51cc45e5815ece3#rd">【来自面试官二面MySQL索引的连续灵魂拷问】</a></p>
        <p>第三段，索引失效场景面试题推荐阅读：<a href="https://mp.weixin.qq.com/s?__biz=Mzg3NjU0NDE4NQ==&amp;mid=2247483801&amp;idx=1&amp;sn=14f7f9e7023abf045c3322a00815f79b&amp;chksm=cf31e84ff8466159498f5db66ed3c028587caabdeabe57aaa5f4612c00ea236e6c6e5bf77a66#rd">【面试官：说说你遇到的MySQL索引失效场景吧，你是如何解决的？】</a></p>
        <p>第四段，查询缓存面试题推荐阅读：<a href="https://mp.weixin.qq.com/s?__biz=Mzg3NjU0NDE4NQ==&amp;mid=2247483836&amp;idx=1&amp;sn=24d090fc782b3855ab4c8c20d139892e&amp;chksm=cf31e86af846617cbee4c7e2deb62fc18fe6e5099e2c20f7cd029a1dcbf9fb4646cfb02a4474#rd">【面试官：什么场景下会导致MySQL缓存失效？生产环境到底要不要开启MySQL缓存？】</a></p>
        <p>第五段，待更新？推荐休闲阅读：<a href="https://mp.weixin.qq.com/mp/appmsgalbum?__biz=Mzg3NjU0NDE4NQ==&amp;action=getalbum&amp;album_id=2218140423993212933#wechat_redirect">【囧么肥事】</a></p>
        <p>更多精彩内容，欢迎关注微信公众号：<strong>囧么肥事</strong> (或搜索：jiongmefeishi)</p>
        <figure><img src="https://img-blog.csdnimg.cn/img_convert/cb3a296f8edbcc70370d4eb569c40634.png" alt="囧么肥事" title="囧么肥事"><figcaption>囧么肥事</figcaption></figure></div></div>
    <!--content E-->
</div>



</body>
<!--left bar tools js S-->
<script src="http://www.jq22.com/jquery/jquery-1.10.2.js"></script>
<script type="text/javascript" src="../../static/js/nav.js"></script>
<!--left bar tools js E-->

<!-- 滚动条 S -->
<script type="text/javascript" src="../../static/js/optiscroll.js"></script>
<!-- 滚动条 E -->

<!--commonjs S-->
<script type="text/javascript" src="../../static/js/common.js"></script>
<!--commonjs E-->

</html>
